[uboot] (第四章)uboot流程

您所在的位置:网站首页 uboot spl 编译 [uboot] (第四章)uboot流程

[uboot] (第四章)uboot流程

2023-04-22 02:51| 来源: 网络整理| 查看: 265

http://blog.csdn.net/ooonebook/article/details/53000893

以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例

[uboot] uboot流程系列: [project X] tiny210(s5pv210)上电启动流程(BL0-BL2) [project X] tiny210(s5pv210)从存储设备加载代码到DDR [uboot] (第一章)uboot流程——概述 [uboot] (第二章)uboot流程——uboot-spl编译流程 [uboot] (第三章)uboot流程——uboot-spl代码流程 [uboot] (第四章)uboot流程——uboot编译流程 [uboot] (番外篇)global_data介绍 [uboot] (番外篇)uboot relocation介绍

建议先看《[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)》,根据例子了解一下上电之后的BL0\BL1\BL2阶段,以及各个阶段的运行位置,功能。 建议先看《[uboot] (第二章)uboot流程——uboot-spl编译流程》,其编译流程基本上是类似的。最大区别在于dtb的编译。

=================================================================================

一、uboot编译和生成文件 0、说明

现在的uboot已经做得和kernel很像,最主要的一点是,uboot也使用了dtb的方法,将设备树和代码分离开来(当然可以通过宏来控制)。 project-x/u-boot/configs/tiny210_defconfig

CONFIG_OF_CONTROL=y // 用于表示是否使用了dtb的方式 CONFIG_OF_SEPARATE=y // 是否将dtb和uboot分离表一

所以在uboot的编译中,和spl的最大区别是还要编译dtb。 (前面我们将的spl是没有使用dtb的,当然好像也可以使用dtb,只是我没有试过)。

1、编译方法

在project X项目中,所有镜像,包括uboot、kernel、rootfs都是放在build目录下进行编译的。具体去参考该项目build的Makefile的实现。 假设config已经配置完成,在build编译命令如下:

make uboot

Makefile中对应的命令如下: project-x/build/Makefile

BUILD_DIR=$(shell pwd) OUT_DIR=$(BUILD_DIR)/out UBOOT_OUT_DIR=$(OUT_DIR)/u-boot UBOOT_DIR=$(BUILD_DIR)/../u-boot uboot: mkdir -p $(UBOOT_OUT_DIR) make -C $(UBOOT_DIR) CROSS_COMPILE=$(CROSS_COMPILE) KBUILD_OUTPUT=$(UBOOT_OUT_DIR) $(BOARD_NAME)_defconfig make -C $(UBOOT_DIR) CROSS_COMPILE=$(CROSS_COMPILE) KBUILD_OUTPUT=$(UBOOT_OUT_DIR) ## -C $(UBOOT_DIR) 指定了要在../uboot,也就是uboot的代码根目录下执行make ## CROSS_COMPILE=$(CROSS_COMPILE) 指定了交叉编译器 ## KBUILD_OUTPUT=$(UBOOT_OUT_DIR) 指定了最终编译的输出目录是build/out/u-boot.

最终,相当于进入了uboot目录执行了make动作。

2、生成文件

最终编译完成之后,会在project-x/build/out/u-boot下生成如下文件:

arch common dts include net tools u-boot.cfg u-boot.lds u-boot.srec board disk examples lib scripts System.map u-boot u-boot.dtb u-boot.map u-boot.sym cmd drivers fs Makefile source test u-boot.bin u-boot-dtb.bin u-boot-nodtb.bin

其中,arch、common、dts、include、board、drivers、fs等等目录是对应代码的编译目录,各个目录下都会生成相应的built.o,是由同目录下的目标文件连接而成。 重点说一下以下几个文件:

文件说明 u-boot 初步链接后得到的uboot文件 u-boot-nodtb.bin 在u-boot的基础上,经过objcopy去除符号表信息之后的可执行程序 u-boot.dtb dtb文件 u-boot-dtb.bin 将u-boot-nodtb.bin和u-boot.dtb打包在一起的文件 u-boot.bin 在需要dtb的情况下,直接由u-boot-dtb.bin复制而来,也就是编译u-boot的最终目标 u-boot.lds uboot的连接脚本 System.map 连接之后的符号表文件 u-boot.cfg 由uboot配置生成的文件 二、uboot编译流程 1、编译整体流程

根据一、2生成的文件说明可知简单流程如下: (1)各目录下built-in.o的生成

源文件、代码文件编译、汇编目标文件同目录目标文件连接built-in目标文件

(2)由所有built-in.o以u-boot.lds为连接脚本通过连接来生成u-boot

built-in目标文件以u-boot.lds为连接脚本进行统一连接u-boot

(3)由u-boot生成u-boot-nodtb.bin

u-bootobjcopy动作去掉符号信息表u-boot-nodtb.bin

(4)由生成uboot的dtb文件

dts文件dtc编译、打包dtb文件u-boot.dtb

(5)由u-boot-nodtb.bin和u-boot.dtb生成u-boot-dtb.bin

u-boot-nodtb.bin和u-boot.dtb追加整合两个文件u-boot-dtb.bin

(6)由u-boot-dtb.bin复制生成u-boot.bin

u-boot-dtb.bin复制u-boot.bin 2、具体编译流程分析

我们直接从make uboot命令分析,也就是从uboot下的Makefile的依赖关系来分析整个编译流程。 注意,这个分析顺序和上述的整体编译流程的顺序是反着的。

(1)入口分析 在project-x/u-boot/Makefile中 all: $(ALL-y) ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg binary_size_check

u-boot.bin就是我们的目标,所以后需要主要研究u-boot.bin的依赖关系。

(2)u-boot.bin的依赖关系 在project-x/u-boot/Makefile中 ifeq ($(CONFIG_OF_SEPARATE),y) ## CONFIG_OF_SEPARATE用于定义是否有DTB并且是否是和uboot分开编译的。 ## tiny210是有定义这个宏的,所以走的是上面这路 u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE $(call if_changed,cat) ## 由u-boot-nodtb.bin和dts/dt.dtb连接在一起,先生成u-boot-dtb.bin ## $(call if_changed,cat)会调用到cmd_cat函数,具体实现我们不分析了 u-boot.bin: u-boot-dtb.bin FORCE $(call if_changed,copy) ## 直接将u-boot-dtb.bin复制为u-boot.bin ## $(call if_changed,copy)会调用到cmd_copy函数,具体实现我们不分析了 else u-boot.bin: u-boot-nodtb.bin FORCE $(call if_changed,copy) endif

对应于上述二、1(5)流程和上述二、1(6)流程。 后续有两个依赖关系要分析,分别是u-boot-nodtb.bin和dts/dt.dtb。 u-boot-nodtb.bin依赖关系参考下述二、2(3)-2(6). dts/dt.dtb依赖关系参考下述二、2(7) 其中u-boot-nodtb.bin的依赖关系和SPL的相当类似,可以先参考一下《[uboot] (第二章)uboot流程——uboot-spl编译流程》。

(3)u-boot-nodtb.bin的依赖关系 在project-x/u-boot/Makefile中 u-boot-nodtb.bin: u-boot FORCE $(call if_changed,objcopy) $(call DO_STATIC_RELA,$ uboot_objdump.txt”进行反编译之后,得到了如下指令

23e00000 : 23e00000: ea0000be b 23e00300 23e00004: e59ff014 ldr pc, [pc, #20] ; 23e00020 23e00008: e59ff014 ldr pc, [pc, #20] ; 23e00024 23e0000c: e59ff014 ldr pc, [pc, #20] ; 23e00028 23e00010: e59ff014 ldr pc, [pc, #20] ; 23e0002c 23e00014: e59ff014 ldr pc, [pc, #20] ; 23e00030 23e00018: e59ff014 ldr pc, [pc, #20] ; 23e00034 23e0001c: e59ff014 ldr pc, [pc, #20] ; 23e00038 // 可以看出以下是异常终端向量表 23e00020 : 23e00020: 23e00060 mvncs r0, #96 ; 0x60 // 其中,23e00020存放的是未定义指令处理函数的地址,也就是23e00060 // 以下以此类推 23e00024 : 23e00024: 23e000c0 mvncs r0, #192 ; 0xc0 23e00028 : 23e00028: 23e00120 mvncs r0, #8 23e0002c : 23e0002c: 23e00180 mvncs r0, #32 23e00030 : 23e00030: 23e001e0 mvncs r0, #56 ; 0x38 23e00034 : 23e00034: 23e00240 mvncs r0, #4 23e00038 : 23e00038: 23e002a0 mvncs r0, #10 23e0003c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}

 

3、符号表中需要注意的符号

前面我们说过了在tiny210中把连接地址设置为0x23e00000。 project-x/build/out/u-boot/spl/u-boot.map

Linker script and memory map Address of section .text set to 0x23e00000 .text 0x23e00000 0x29b28 *(.__image_copy_start) .__image_copy_start 0x23e00000 0x0 arch/arm/lib/built-in.o 0x23e00000 __image_copy_start *(.vectors) .vectors 0x23e00000 0x300 arch/arm/lib/built-in.o 0x23e00000 _start 0x23e00020 _undefined_instruction 0x23e00024 _software_interrupt 0x23e00028 _prefetch_abort 0x23e0002c _data_abort 0x23e00030 _not_used 0x23e00034 _irq 0x23e00038 _fiq 0x23e00040 IRQ_STACK_START_IN *(.__image_copy_end) .__image_copy_end 0x23e36b78 0x0 arch/arm/lib/built-in.o *(.__rel_dyn_start) .__rel_dyn_start 0x23e36b78 0x0 arch/arm/lib/built-in.o *(.__rel_dyn_end) .__rel_dyn_end 0x23e3cbb8 0x0 arch/arm/lib/built-in.o 0x23e3cbb8 _image_binary_end = . *(.__bss_start) .__bss_start 0x23e36b78 0x0 arch/arm/lib/built-in.o 0x23e36b78 __bss_start .__bss_end 0x23e6b514 0x0 arch/arm/lib/built-in.o 0x23e6b514 __bss_end

 

重点关注 * __image_copy_start & __image_copy_end 界定了代码空间的位置,用于重定向代码的时候使用,在uboot relocate的过程中,需要把这部分拷贝到uboot的新的地址空间中,后续在新地址空间中运行。 具体可以参考《[uboot] (番外篇)uboot relocation介绍》。 * _start 在u-boot-spl.lds中ENTRY(_start),也就规定了代码的入口函数是_start。所以后续分析代码的时候就是从这里开始分析。 * __rel_dyn_start & __rel_dyn_end 由链接器生成,存放了绝对地址符号的label的地址,用于修改uboot relocate过程中修改绝对地址符号的label的值。 具体可以参考《[uboot] (番外篇)uboot relocation介绍》。 * _image_binary_end

综上,u-boot的编译就完成了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3